﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2014-04-20 17:50
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BassDrop.Core.Common.Data
{
	/// <summary>
	/// Class containing the custom metadata for a file, eg. the items in the
	/// xdata sections of an xplf playlist file.
	/// </summary>
	public class CustomMetadata
	{
		private Dictionary<string, CustomMetadataItem> m_items;

		/// <summary>
		/// Construct a new custom metadata collection
		/// </summary>
		public CustomMetadata()
		{
			m_items = new Dictionary<string, CustomMetadataItem>();
		}

		/// <summary>
		/// Adds a new item to the metadata collection.
		/// The created item is returned so that its other properties can be set.
		/// </summary>
		/// <param name="key">the key of the item to add</param>
		/// <param name="value">the value of the item to add as string</param>
		public CustomMetadataItem AddItem( string key, string value )
		{
			CustomMetadataItem item = new CustomMetadataItem( key, value, this );
			m_items.Add( key, item );

			return item;
		}

		/// <summary>
		/// Gets the item with the passed key from the collection.
		/// If no such item exists, throws an exception
		/// </summary>
		/// <param name="key">the key of the item to get</param>
		/// <returns></returns>
		public CustomMetadataItem GetItem( string key )
		{
			return m_items[key];
		}

		/// <summary>
		/// Gets the item with the passed key from the collection.
		/// If no such item exists, throws an exception
		/// </summary>
		/// <param name="key">the key of the item to get</param>
		/// <returns></returns>
		public CustomMetadataItem this[string key]
		{
			get
			{
				return GetItem( key );
			}
		}

		/// <summary>
		/// Returns whether an item with the passed key is in the collection
		/// </summary>
		/// <param name="key">the key to check</param>
		/// <returns></returns>
		public bool ContainsItem( string key )
		{
			return m_items.ContainsKey( key );
		}

		/// <summary>
		/// Gets the item with the passed key from the collection.
		/// If no such item exists, returns null
		/// </summary>
		/// <param name="key">the key of the item to get</param>
		/// <returns></returns>
		public CustomMetadataItem TryGetItem( string key )
		{
			if ( ContainsItem( key ) )
			{
				return m_items[key];
			}

			return null;
		}

		/// <summary>
		/// Returns the list of items applicable for the passed client / application and location / machine from
		/// this metadata collection. If null is passed for either parameters or it is left out, items for
		/// all such parameters are returned.
		/// </summary>
		/// <param name="client">If a non-null value is passed, will only return items compatible with this type of application</param>
		/// <param name="location">If a non-null value is passed, will only return items compatible with this location / machine</param>
		/// <returns></returns>
		public IEnumerable<CustomMetadataItem> GetItemsFor( string client = null, string location = null )
		{
			foreach ( var item in m_items.Values )
			{
				if ( item.DoesApplyFor( client, location ) )
				{
					yield return item;
				}
			}
		}

		#region Inner classes

		/// <summary>
		/// A piece of custom metadata, eg. an item inside an xdata section of an xplf playlist file
		/// </summary>
		public class CustomMetadataItem : CustomDataItemBase<CustomMetadata>
		{
			/// <summary>
			/// The key of this piece of metadata
			/// </summary>
			public string Key
			{
				get;
				private set;
			}

			/// <summary>
			/// The value of this piece of metadata as a string
			/// </summary>
			public string Value
			{
				get;
				private set;
			}

			/// <summary>
			/// Creates a new custom metadata item
			/// </summary>
			/// <param name="key">the key of this metadata item</param>
			/// <param name="value">the value of this metadata item as a string</param>
			/// <param name="parent">the CustomMetadata object containing this object</param>
			public CustomMetadataItem( string key, string value, CustomMetadata parent )
				: base( parent )
			{
				Key = key;
				Value = value;
			}
		}

		#endregion Inner classes
	}
}
